/*
 * Copyright (C) 2015-2016  Nicola Spanti (RyDroid) <dev@nicola-spanti.info>
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */


#include <check.h>
#include "PlanetWars2dRT-core/specific/model/universe.h"
#include "PlanetWars2dRT-core/specific/model/planet_default.h"
#include "PlanetWars2dRT-core/specific/model/ship.h"
#include "check_observable_generic.h"


struct universe_t a_universe;
struct planet_t   a_planet;
struct ship_t     a_ship;
struct observer_t an_observer;

void
tests_setup_init(void)
{
  universe_init_first_time_only(&a_universe);
  a_universe.size.x = 450;
  a_universe.size.y = 450;
  
  planet_set_default(&a_planet);
  a_planet.player_index = 0;
  
  position_2d_uint pos = { 0, 0 };
  a_ship = ship_create_default(&pos, &pos);
  
  observer_init_first_time_only_unsafe(&an_observer);
}

void
tests_setup_free(void)
{
  universe_destructor(&a_universe);
  observer_init_first_time_only_unsafe(&an_observer);
}


bool
universe_add_observer_generic(void* a_universe,
			      const observer_t* an_observer)
{
  return universe_add_observer(a_universe, an_observer);
}

void
universe_remove_observers_generic(void* a_universe)
{
  universe_remove_observers(a_universe);
}

void
universe_notify_observers_generic(void* a_universe, void* data)
{
  universe_notify_observers(a_universe, data);
}

size_t
universe_get_nb_observers_generic(void* a_universe)
{
  return universe_get_nb_observers(a_universe);
}

START_TEST(test_add_observer)
{
  test_add_observer_generic(&a_universe,
			    universe_add_observer_generic);
}
END_TEST

START_TEST(test_remove_observers)
{
  test_remove_observers_generic(&a_universe,
				universe_add_observer_generic,
				universe_remove_observers_generic,
				universe_get_nb_observers_generic);
}
END_TEST

START_TEST(test_notify_observers)
{
  test_notify_observers_generic(&a_universe,
				universe_add_observer_generic,
				universe_notify_observers_generic);
}
END_TEST


Suite*
universe_observers_suite(void)
{
  Suite* s = suite_create("Observers of universe");
  
  TCase* tc_observers_base = tcase_create("Base");
  tcase_add_checked_fixture(tc_observers_base,
			    tests_setup_init, tests_setup_free);
  tcase_add_test(tc_observers_base,
		 test_add_observer);
  tcase_add_test(tc_observers_base,
		 test_remove_observers);
  tcase_add_test(tc_observers_base,
		 test_notify_observers);
  suite_add_tcase(s, tc_observers_base);
  
  TCase* tc_observers_events = tcase_create("Events");
  tcase_add_checked_fixture(tc_observers_events,
			    tests_setup_init, tests_setup_free);
  /* TODO */
  suite_add_tcase(s, tc_observers_events);
  
  return s;
}

int
main(void)
{
  size_t number_failed;
  Suite* s;
  SRunner* sr;

  s = universe_observers_suite();
  sr = srunner_create(s);
  
  srunner_run_all(sr, CK_NORMAL);
  number_failed = srunner_ntests_failed(sr);
  srunner_free(sr);
  
  return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}
